package com.zeyu.framework.tools.report.convert.pool;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Queue;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 抽象的对象池,提供基本实现
 * Created by zeyuphoenix on 16/9/3.
 */
public abstract class AbstractPool<T> implements ObjectPool<T> {

    // ================================================================
    // Constants
    // ================================================================

    /**
     * logger
     */
    protected static final Logger logger = LoggerFactory.getLogger("pool");

    // ================================================================
    // Fields
    // ================================================================

    // 对象工厂
    final ObjectFactory<T> objectFactory;
    // 队列
    Queue<T> queue;
    // 对象池大小
    final AtomicInteger poolSize = new AtomicInteger(0);
    // 最大等待
    int maxWait;
    // 容量
    final int capacity;
    // 停留时间
    final long retentionTime;

    // ================================================================
    // Constructors
    // ================================================================

    /**
     * 构造函数
     */
    public AbstractPool(ObjectFactory<T> objectFactory, int number,
                        int maxWait, Long retentionTime) throws PoolException {
        this.objectFactory = objectFactory;
        this.capacity = number;
        this.maxWait = maxWait;
        this.retentionTime = retentionTime;
    }

    // ================================================================
    // Methods from/for super Interfaces or SuperClass
    // ================================================================

    @Override
    public void createObject() {
        T object = objectFactory.create();
        queue.add(object);
        poolSize.getAndIncrement();
    }

    @Override
    public void destroyObject(T object) {
        objectFactory.destroy(object);
    }

    @Override
    public void poolCleaner() throws InterruptedException, PoolException {

        logger.debug("HC: queue size: " + queue.size() + " poolSize "
                + poolSize.get());

        int size = poolSize.get();
        // remove invalid objects
        for (int i = 0; i < size; i++) {
            T object = borrowObject();
            if (object == null) {
                logger.debug("HC: object is null");
            } else {
                logger.debug("HC: validating " + object.toString());
                if (!objectFactory.validate(object)) {
                    logger.debug("HC: destroying " + object.toString());
                    destroyObject(object);
                } else {
                    returnObject(object, false);
                }
            }
        }

        int number = poolSize.get() - capacity;
        logger.debug("in clean pool, the surplus or shortage is: " + number);
        synchronized (this) {
            int iterations = Math.abs(number);
            for (int i = 0; i < iterations; i++) {
                if (number < 1) {
                    this.createObject();
                } else {
                    T object = borrowObject();
                    this.destroyObject(object);
                }
            }
        }
    }

    // ================================================================
    // Public or Protected Methods
    // ================================================================

    // ================================================================
    // Getter & Setter
    // ================================================================

    public int getMaxWait() {
        return maxWait;
    }

    public void setMaxWait(int maxWait) {
        this.maxWait = maxWait;
    }

    // ================================================================
    // Private Methods
    // ================================================================

    // ================================================================
    // Inner or Anonymous Class
    // ================================================================

    // ================================================================
    // Test Methods
    // ================================================================

}
